package com.tiance.base;

import com.alibaba.fastjson.JSON;
import com.tiance.dal.dao.RolePermissionDAO;
import com.tiance.dal.dao.UserDAO;
import com.tiance.dal.dataobject.RolePermissionDO;
import com.tiance.dal.dataobject.UserDO;
import com.tiance.domainservice.service.RolePermissionService;
import com.tiance.domainservice.service.UserService;
import com.tiance.shiro.utils.ShiroUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 *
 * @author 雷霆
 * @version 1.0.0
 * @date$ 2019/1/30
 *
 * Description：
 *
 * Modification History:
 *
 */
public class ShiroRealm extends AuthorizingRealm {
    private static final Logger logger = LoggerFactory.getLogger(ShiroRealm.class);

    @Autowired
    private UserService userService;

    @Autowired
    private RolePermissionService rolePermissionService;

    /**
     * 验证权限信息，根据account从表中查询出权限并放到
     * AuthorizationInfo中
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        logger.info("进入 权限校验 逻辑-doGetAuthorizationInfo--->");

        UserDO user = userService.queryUserByUserName(principals.toString());
        if (user == null) {
            throw new UnknownAccountException();
        }

        Set<String> stringPermissionSet=rolePermissionService.queryRolePermissionSetByRoleId(user.getRoleId());

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        authorizationInfo.setStringPermissions(stringPermissionSet);

         logger.info(" 权限校验 结束--> 获取authorizationInfo: " + JSON.toJSONString(authorizationInfo));
        return authorizationInfo;

    }

    /**
     * 验证身份信息
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        logger.info("进入 身份校验 逻辑-doGetAuthenticationInfo--->");

        LoginToken loginToken=(LoginToken)token;
        UserDO user = userService.queryUserByUserName(loginToken.getUsername());
        if (user == null) {
            throw new UnknownAccountException();
        }

        //处理session
        DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
        DefaultWebSessionManager sessionManager = (DefaultWebSessionManager)securityManager.getSessionManager();
        Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();//获取当前已登录的用户session列表
        for(Session session:sessions){
            String sessionKey = String.valueOf(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY));
            //清除该用户以前登录时保存的session
            if(user.getUserName().equals(sessionKey)) {
                logger.info("--doGetAuthenticationInfo--遍历获取到已经存在的session的key:"+sessionKey);
                sessionManager.getSessionDAO().delete(session);
            }
        }

     /*   Date lockEndTime = dto.getLockEndTime();
        logger.info("---获取到LockTime: "+lockEndTime);
        if (null != lockEndTime && lockEndTime.after(new Date())) {
            logger.info("---进入账号锁定逻辑，抛异常");
            throw new LockedAccountException("账号已被锁定，请稍后重试");
        }*/
        return new SimpleAuthenticationInfo(
                user.getUserName(), user.getPassWord(),
                ByteSource.Util.bytes(user.getUserName()),
                getName());
    }


    /**
     * 设置认证加密方式
     */
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher md5CredentialsMatcher = new HashedCredentialsMatcher();
        md5CredentialsMatcher.setHashAlgorithmName(ShiroUtil.hashAlgorithmName);
        md5CredentialsMatcher.setHashIterations(ShiroUtil.hashIterations);
        super.setCredentialsMatcher(md5CredentialsMatcher);
    }
    /**
     * 实际做密码校验的逻辑
     */
    @Override
    protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)
            throws AuthenticationException {
        logger.info("进入 密码校验 逻辑-assertCredentialsMatch--->");

        CredentialsMatcher cm = getCredentialsMatcher();
        if (cm != null) {
            if (!cm.doCredentialsMatch(token, info)) {
                //not successful - throw an exception to indicate this:
                String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";
                throw new IncorrectCredentialsException(msg);
            }
        }
        logger.info("结束 密码校验 逻辑-assertCredentialsMatch--->");

    }

    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }


}
